﻿#region

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.Script.Serialization;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
using RGG.sharp;

#endregion

namespace RGG
{
    [Serializable]
    public class RussianGridGameConfig : IXmlSerializable
    {
        private static RussianGridGameConfig _instance;
        private Color _currentGbBkColor;
        private Color _currentHorizontalGridLineColor;
        private int _currentHorizontalGridLineWidth;
        private int _currentPerCellSize;
        private Color _currentVerticalGridLineColor;
        private int _currentVerticalGridLineWidth;
        private Color _nextHorizontalGridLineColor;
        private int _nextHorizontalGridLineWidth;
        private int _nextPerCellSize;
        private Color _nextVerticalGridLineColor;
        private int _nextVerticalGridLineWidth;
        private int _currentKeyMapIndex;
        private int _height;
        private bool _isDrawCurrentPbGridLine;
        private List<Dictionary<string, string>> _keyMaps;
        private int _keyMapSolution;
        private int[] _scores;
        private int _width;

        private RussianGridGameConfig()
        {
        }

        /// <summary>
        ///     整个游戏的高度（小格为单位）
        /// </summary>
        public int Height
        {
            get { return _height; }
            set { _height = value; }
        }

        /// <summary>
        ///     整个游戏的宽度（小格为单位）
        /// </summary>
        public int Width
        {
            get { return _width; }
            set { _width = value; }
        }

        /// <summary>
        ///     越大速度越慢，默认值为1000ms
        /// </summary>
        public int Speed { set; get; }

        /// <summary>
        ///     评分标准，消除0条为Scores[0]，消除1条为Scores[1]，最大值为4
        /// </summary>
        public int[] Scores
        {
            get
            {
                if (_scores == null)
                {
                    _scores = new int[] {0, 10, 25, 45, 70};
                }
                return _scores;
            }
        }

        /// <summary>
        ///     水平方向上的网格线的颜色值
        ///     返回值为颜色的Argb值
        /// </summary>
        private string CurrentHorizontalGridLineColorString
        {
            get { return _currentHorizontalGridLineColor.ToArgb().ToString("X8"); }
            set
            {
                Regex regex = new Regex("[0-9a-zA-Z]{6,8}");
                if (regex.IsMatch(value))
                {
                    _currentHorizontalGridLineColor =
                        Color.FromArgb(int.Parse(value, System.Globalization.NumberStyles.AllowHexSpecifier));
                }
                else
                {
                    _currentHorizontalGridLineColor = Color.FromName(value);
                }
                Debug.Assert(_currentHorizontalGridLineColor != null, "颜色参数提供错误");
            }
        }

        /// <summary>
        ///     水平方向上的网格线的颜色值
        /// </summary>
        public Color CurrentHorizontalGridLineColor
        {
            set { _currentHorizontalGridLineColor = value; }
            get { return _currentHorizontalGridLineColor; }
        }

        public int CurrentHorizontalGridLineWidth
        {
            set { _currentHorizontalGridLineWidth = value; }
            get { return _currentHorizontalGridLineWidth; }
        }

        /// <summary>
        ///     垂直方向上的网格线的颜色值(ARGB)
        /// </summary>
        private string CurrentVerticalGridLineColorString
        {
            get { return _currentHorizontalGridLineColor.ToArgb().ToString("X8"); }
            set
            {
                Regex regex = new Regex("[0-9a-zA-Z]{6,8}");
                if (regex.IsMatch(value))
                {
                    _currentVerticalGridLineColor =
                        Color.FromArgb(int.Parse(value, System.Globalization.NumberStyles.AllowHexSpecifier));
                }
                else
                {
                    _currentVerticalGridLineColor = Color.FromName(value);
                }
                Debug.Assert(_currentVerticalGridLineColor != null, "颜色参数提供错误");
            }
        }

        /// <summary>
        ///     垂直方向上的网格线的颜色值
        /// </summary>
        public Color CurrentVerticalGridLineColor
        {
            set { _currentVerticalGridLineColor = value; }
            get { return _currentVerticalGridLineColor; }
        }

        /// <summary>
        ///     网格水平分割线宽度
        /// </summary>
        public int CurrentVerticalGridLineWidth
        {
            set { _currentVerticalGridLineWidth = value; }
            get { return _currentVerticalGridLineWidth; }
        }

        /// <summary>
        ///     每个单元格的大小
        /// </summary>
        public int CurrentPerCellSize
        {
            get { return _currentPerCellSize; }
            set { _currentPerCellSize = value; }
        }

        public bool IsDrawNextPbGridLine{set; get; }

        /// <summary>
        ///     水平方向上的网格线的颜色值
        ///     返回值为颜色的Argb值
        /// </summary>
        private string NextHorizontalGridLineColorString
        {
            get { return _nextHorizontalGridLineColor.ToArgb().ToString("X8"); }
            set
            {
                Regex regex = new Regex("[0-9a-zA-Z]{6,8}");
                if (regex.IsMatch(value))
                {
                    _nextHorizontalGridLineColor =
                        Color.FromArgb(int.Parse(value, System.Globalization.NumberStyles.AllowHexSpecifier));
                }
                else
                {
                    _nextHorizontalGridLineColor = Color.FromName(value);
                }
                Debug.Assert(_nextHorizontalGridLineColor != null, "颜色参数提供错误");
            }
        }

        /// <summary>
        ///     水平方向上的网格线的颜色值
        /// </summary>
        public Color NextHorizontalGridLineColor
        {
            set { _nextHorizontalGridLineColor = value; }
            get { return _nextHorizontalGridLineColor; }
        }

        public int NextHorizontalGridLineWidth
        {
            set { _nextHorizontalGridLineWidth = value; }
            get { return _nextHorizontalGridLineWidth; }
        }

        /// <summary>
        ///     垂直方向上的网格线的颜色值(ARGB)
        /// </summary>
        private string NextVerticalGridLineColorString
        {
            get { return _nextHorizontalGridLineColor.ToArgb().ToString("X8"); }
            set
            {
                Regex regex = new Regex("[0-9a-zA-Z]{6,8}");
                if (regex.IsMatch(value))
                {
                    _nextVerticalGridLineColor =
                        Color.FromArgb(int.Parse(value, System.Globalization.NumberStyles.AllowHexSpecifier));
                }
                else
                {
                    _nextVerticalGridLineColor = Color.FromName(value);
                }
                Debug.Assert(_nextVerticalGridLineColor != null, "颜色参数提供错误");
            }
        }

        /// <summary>
        ///     垂直方向上的网格线的颜色值
        /// </summary>
        public Color NextVerticalGridLineColor
        {
            set { _nextVerticalGridLineColor = value; }
            get { return _nextVerticalGridLineColor; }
        }

        /// <summary>
        ///     网格水平分割线宽度
        /// </summary>
        public int NextVerticalGridLineWidth
        {
            set { _nextVerticalGridLineWidth = value; }
            get { return _nextVerticalGridLineWidth; }
        }

        /// <summary>
        ///     每个单元格的大小
        /// </summary>
        public int NextPerCellSize
        {
            get { return _nextPerCellSize; }
            set { _nextPerCellSize = value; }
        }

        /// <summary>
        ///     背景颜色,16进制字符串或者颜色的名字
        /// </summary>
        private string CurrentGbBkColorString
        {
            set
            {
                Regex regex = new Regex("^[0-9a-fA-F]{6,8}$");
                if (regex.IsMatch(value))
                {
                    _currentGbBkColor = Color.FromArgb(int.Parse(value, System.Globalization.NumberStyles.AllowHexSpecifier));
                }
                else
                {
                    _currentGbBkColor = Color.FromName(value);
                }
            }
            get { return _currentGbBkColor.ToArgb().ToString("X8"); }
        }

        /// <summary>
        ///     配置文件里面的按键映射
        /// </summary>
        private int KeyMapSolution
        {
            get { return _keyMapSolution; }
            set { _keyMapSolution = value; }
        }

        /// <summary>
        ///     描述是否绘制网格线
        /// </summary>
        public bool IsDrawCurrentPbGridLine
        {
            get { return _isDrawCurrentPbGridLine; }
            set { _isDrawCurrentPbGridLine = value; }
        }

        private List<Dictionary<string, string>> KeyMaps
        {
            get { return _keyMaps; }
            set { _keyMaps = value; }
        }

        public Dictionary<string, string> CurrentKeyMap
        {
            get { return KeyMaps[CurrentKeyMapIndex]; }
        }

        public int CurrentKeyMapIndex
        {
            get { return _currentKeyMapIndex; }
            private set { _currentKeyMapIndex = value; }
        }

        public Color CurrentGbBkColor
        {
            get { return _currentGbBkColor; }
            set { _currentGbBkColor = value; }
        }

        /// <summary>
        ///     背景颜色,16进制字符串或者颜色的名字
        /// </summary>
        private string NextGbBkColorString
        {
            set
            {
                Regex regex = new Regex("^[0-9a-fA-F]{6,8}$");
                if (regex.IsMatch(value))
                {
                    NextGbBkColor = Color.FromArgb(int.Parse(value, System.Globalization.NumberStyles.AllowHexSpecifier));
                }
                else
                {
                    NextGbBkColor = Color.FromName(value);
                }
            }
            get { return NextGbBkColor.ToArgb().ToString("X8"); }
        }
        public Color NextGbBkColor { get;private set; }

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            if (reader.Name == "RussianGridGameConfig") reader.ReadToDescendant("Height");
            Height = reader.ReadElementContentAsInt();
            Width = reader.ReadElementContentAsInt();
            Speed = reader.ReadElementContentAsInt();
            CurrentGbBkColorString = reader.ReadElementContentAsString();
            IsDrawCurrentPbGridLine = bool.Parse(reader.ReadElementContentAsString());
            CurrentPerCellSize = reader.ReadElementContentAsInt();
            CurrentHorizontalGridLineColorString = reader.ReadElementContentAsString();
            CurrentHorizontalGridLineWidth = reader.ReadElementContentAsInt();
            CurrentVerticalGridLineColorString = reader.ReadElementContentAsString();
            CurrentVerticalGridLineWidth = reader.ReadElementContentAsInt();
            NextGbBkColorString = reader.ReadElementContentAsString();
            IsDrawNextPbGridLine = bool.Parse(reader.ReadElementContentAsString());
            NextPerCellSize = reader.ReadElementContentAsInt();
            NextHorizontalGridLineColorString = reader.ReadElementContentAsString();
            NextHorizontalGridLineWidth = reader.ReadElementContentAsInt();
            NextVerticalGridLineColorString = reader.ReadElementContentAsString();
            NextVerticalGridLineWidth = reader.ReadElementContentAsInt();
            KeyMaps = new List<Dictionary<string, string>>();
            JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
            while (reader.ReadToDescendant("KeyMap"))
            {
                KeyMaps.Add(jsSerializer.Deserialize<Dictionary<string, string>>(reader.ReadElementString()));
            }
            reader.ReadEndElement();
            reader.ReadEndElement();
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteElementString("Height", Height.ToString());
            writer.WriteElementString("Width", Width.ToString());
            writer.WriteElementString("Speed", Speed.ToString());
            writer.WriteElementString("CurrentGbBkColor", CurrentGbBkColorString);
            writer.WriteElementString("IsDrawCurrentPbGridLine", IsDrawCurrentPbGridLine.ToString());
            writer.WriteElementString("CurrentPerCellSize", CurrentPerCellSize.ToString());
            writer.WriteElementString("CurrentHorizontalGridLineColor", CurrentHorizontalGridLineColorString);
            writer.WriteElementString("CurrentHorizontalGridLineWidth", CurrentHorizontalGridLineWidth.ToString());
            writer.WriteElementString("CurrentVerticalGridLineColor", CurrentVerticalGridLineColorString);
            writer.WriteElementString("CurrentVerticalGridLineWidth", CurrentVerticalGridLineWidth.ToString());
            writer.WriteElementString("NextGbBkColor", CurrentGbBkColorString);
            writer.WriteElementString("IsDrawNextPbGridLine", IsDrawCurrentPbGridLine.ToString());
            writer.WriteElementString("NextPerCellSize", NextPerCellSize.ToString());
            writer.WriteElementString("NextHorizontalGridLineColor", NextHorizontalGridLineColorString);
            writer.WriteElementString("NextHorizontalGridLineWidth", NextHorizontalGridLineWidth.ToString());
            writer.WriteElementString("NextVerticalGridLineColor", NextVerticalGridLineColorString);
            writer.WriteElementString("NextVerticalGridLineWidth", NextVerticalGridLineWidth.ToString());
            //写键盘映射
            writer.WriteStartElement("KeyMaps");
            JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
            StringBuilder sb = new StringBuilder();
            foreach (var KeyMap in KeyMaps)
            {
                sb.Clear();
                jsSerializer.Serialize(KeyMap, sb);
                writer.WriteElementString("KeyMap", sb.ToString());
            }
            writer.WriteEndElement();
        }

        /// <summary>
        ///     保存对配置的更改
        /// </summary>
        public void StoreAsConfigFile()
        {
            var configFilePath = ConfigurationManager.AppSettings["RussianGridGameConfigPath"];
            var xmlSerializer = new XmlSerializer(typeof (RussianGridGameConfig));
            if (File.Exists(configFilePath))
            {
                File.Delete(configFilePath);
            }
            xmlSerializer.Serialize(new FileStream(configFilePath, FileMode.Create, FileAccess.Write), this);
        }

        /// <summary>
        ///     获取对象的实例
        /// </summary>
        /// <returns></returns>
        public static RussianGridGameConfig GetInstance(int keyMapSolutionIndex = 0)
        {
            if (_instance == null)
            {
                var configFilePath = ConfigurationManager.AppSettings["RussianGridGameConfigPath"];
                var xmlSerializer = new XmlSerializer(typeof (RussianGridGameConfig));
                RussianGridGameConfig instance = null;
                if (File.Exists(configFilePath) &&
                    xmlSerializer.CanDeserialize(
                        new XmlTextReader(new FileStream(configFilePath, FileMode.Open, FileAccess.Read))))
                {
                    instance =
                        xmlSerializer.Deserialize(
                            new FileStream(configFilePath,
                                FileMode.Open, FileAccess.Read)) as RussianGridGameConfig;
                    if (_instance == null)
                    {
                        _instance = instance;
                    }
                }
                else
                {
                    ResetConfigFile();
                }
            }
            Debug.Assert(_instance != null, "_instance != null");
            _instance.CurrentKeyMapIndex = keyMapSolutionIndex;
            return _instance;
        }

        /// <summary>
        ///     重置配置文件，该函数会重置_instance对象
        /// </summary>
        public static void ResetConfigFile()
        {
            RussianGridGameConfig instance = null;
            instance = new RussianGridGameConfig
            {
                Height = 40,
                Width = 20,
                Speed = 1000,
                CurrentGbBkColor = Color.Black,
                IsDrawCurrentPbGridLine = true,
                CurrentVerticalGridLineColor = Color.White,
                CurrentVerticalGridLineWidth = 1,
                CurrentHorizontalGridLineColor = Color.White,
                CurrentHorizontalGridLineWidth = 1,
                NextGbBkColor = Color.Black,
                IsDrawNextPbGridLine = true,
                NextVerticalGridLineColor = Color.White,
                NextVerticalGridLineWidth = 1,
                NextHorizontalGridLineColor = Color.White,
                NextHorizontalGridLineWidth = 1,
                CurrentPerCellSize = 10,
                NextPerCellSize =  10,
                KeyMaps = new List<Dictionary<string, string>>
                {
                    new Dictionary<string, string>
                    {
                        {Keys.Up.ToString(), KeyDownDirection.Up.ToString()},
                        {Keys.Down.ToString(), KeyDownDirection.Down.ToString()},
                        {Keys.Left.ToString(), KeyDownDirection.Left.ToString()},
                        {Keys.Right.ToString(), KeyDownDirection.Right.ToString()}
                    },
                    new Dictionary<string, string>
                    {
                        {Keys.W.ToString(), KeyDownDirection.Up.ToString()},
                        {Keys.S.ToString(), KeyDownDirection.Down.ToString()},
                        {Keys.A.ToString(), KeyDownDirection.Left.ToString()},
                        {Keys.D.ToString(), KeyDownDirection.Right.ToString()}
                    }
                }
            };
            _instance = instance;
            instance.StoreAsConfigFile();
        }
    }
}